/**
 * Copyright (C) 2010 Hamburg Sud
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hamburgsud.log4testing.core.data;

import java.util.ArrayList;
import java.util.ListIterator;

import org.joda.time.DateTime;

/**
 * Represents the parent class of the TestCase, TestStepGroup and TestSuite
 * 
 * @author
 * 
 */
abstract public class TestStepContainer extends TestObject {

	private String name = "";

	/**
	 * Calls the constructor of the super Class
	 * 
	 * @param name
	 *            Name of the TestStepContainer
	 */
	public TestStepContainer(final String name) {
		setName(name);
	}

	/**
	 * 
	 * @param name
	 *            the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	abstract public TestStep getFirstTestStep();

	abstract public TestStep getLastTestStep();

	abstract public int getNumberOfTestSteps();

	abstract public int getNumberOfFailed();

	abstract public TestStep getFirstFailed();
	
	/**
	 * Removes all of the elements from this container. The list will be empty
	 * after this call returns.
	 */
	abstract public void clear();

	/**
	 * Calculates the number of failed TestSteps
	 * 
	 * @param iterable
	 *            the container in which the TestSuite/TestCase/TestStepGroups
	 *            are stored
	 * @return number of TestSteps
	 */
	final protected int getNumberOfFailed(
			Iterable<? extends TestStepContainer> iterable) {
		int numberOfFailed = 0;
		for (TestStepContainer testStepContainer : iterable) {
			numberOfFailed += testStepContainer.getNumberOfFailed();
		}
		return numberOfFailed;
	}

	/**
	 * Calculates the number of TestSteps
	 * 
	 * @param iterable
	 *            the container in which the TestSuite/TestCase/TestStepGroups
	 *            are stored
	 * @return number of TestSteps
	 */
	final protected int getNumberOfTestSteps(
			Iterable<? extends TestStepContainer> iterable) {
		int numberOfTestSteps = 0;
		for (TestStepContainer testStepContainer : iterable) {
			numberOfTestSteps += testStepContainer.getNumberOfTestSteps();
		}
		return numberOfTestSteps;
	}

	/**
	 * Returns the first Failed TestStep
	 * 
	 * @param iterable
	 *            the container in which the TestSuite/TestCase/TestStepGroups
	 *            are stored
	 * @return first failed TestStep
	 */
	final protected TestStep getFirstFailed(
			Iterable<? extends TestStepContainer> iterable) {
		TestStep firstFailed = null;
		for (TestStepContainer testStepContainer : iterable) {
			firstFailed = testStepContainer.getFirstFailed();
			if (firstFailed != null) {
				break;
			}
		}
		return firstFailed;
	}

	/**
	 * Returns the first TestStep
	 * 
	 * @param iterable
	 *            the container in which the TestSuite/TestCase/TestStepGroups
	 *            are stored
	 * @return first TestStep
	 */
	final protected TestStep getFirstTestStep(
			Iterable<? extends TestStepContainer> iterable) {
		TestStep firstTestStep = null;
		for (TestStepContainer testStepContainer : iterable) {
			firstTestStep = testStepContainer.getFirstTestStep();
			if (firstTestStep != null) {
				break;
			}
		}
		return firstTestStep;
	}

	/**
	 * Returns the last TestStep
	 * 
	 * @param testStepContainers
	 *            which contains all TestSuites/TestCases/TestStepGroups
	 * @return last TestStep
	 */
	final protected TestStep getLastTestStep(
			ArrayList<? extends TestStepContainer> testStepContainers) {
		TestStep lastTestStep = null;
		final ListIterator<? extends TestStepContainer> iterator = testStepContainers
				.listIterator(testStepContainers.size());
		while (iterator.hasPrevious()) {
			final TestStepContainer testStepContainer = iterator.previous();
			lastTestStep = testStepContainer.getLastTestStep();
			if (lastTestStep != null) {
				break;
			}
		}
		return lastTestStep;
	}

	/**
	 * Returns the finishing Time of the TestStepContainer
	 */
	@Override
	public DateTime getFinishingTime() {
		final TestStep lastTestStep = getLastTestStep();
		if (lastTestStep == null) {
			return null;
		} else {
			return lastTestStep.getFinishingTime();
		}
	}

	/**
	 * Returns the starting Time of the TestStepContainer which is the starting
	 * time of the first test step of this container.
	 */
	@Override
	public DateTime getStartingTime() {
		final TestStep firstTestStep = getFirstTestStep();
		if (firstTestStep == null) {
			return null;
		} else {
			return firstTestStep.getStartingTime();
		}
	}

	/**
	 * Checks if the TestStepContainer is failed. That is the case when at least
	 * one test step has the status {@link TestStatus#ERROR} or
	 * {@link TestStatus#EXCEPTION}.
	 * 
	 * @return boolean if the TestStepContainer is failed
	 */
	@Override
	public boolean isFailed() {
		final TestStep firstFailed = getFirstFailed();
		if (firstFailed == null) {
			return false;
		} else {
			return true;
		}
	}

}
